package com.xliang.security.sensitive;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class SensitiveWordsFilter
{
    //敏感词库
    private static Map<Object, Object> sensitiveWordMap = null;
    
    /**
     * 初始化关键词库
     * @param words
     */
    @SuppressWarnings("unchecked")
    public static void createSensitiveWordMap(Set<String> words)
    {
        sensitiveWordMap = new HashMap<>(words.size());
        String key = null;
        Map<Object, Object> currMap = null;
        Iterator<String> iterator = words.iterator();
        while (iterator.hasNext())
        {
            key = iterator.next(); //关键字  
            currMap = sensitiveWordMap;
            for (int i = 0; i < key.length(); i++)
            {
                char keyChar = key.charAt(i); //转换成char型  
                Object wordMap = currMap.get(keyChar); //获取  
                
                if (wordMap != null)
                {
                    //如果存在该key，直接赋值  
                    currMap = (Map<Object, Object>)wordMap;
                }
                else
                {
                    //不存在则，则构建一个map，同时将isEnd设置为0，因为他不是最后一个  
                    Map<Object, Object> newMap = new HashMap<>();
                    newMap.put("isEnd", "false"); //不是最后一个  
                    currMap.put(keyChar, newMap);
                    currMap = newMap;
                }
                if (i == key.length() - 1)
                {
                    currMap.put("isEnd", "true"); //最后一个  
                }
            }
        }
    }
    
    /**
     * 返回text中关键词列表
     * @param text
     * @return
     */
    @SuppressWarnings("unchecked")
    public static List<String> checkSensitiveWord(String text)
    {
        List<String> sensitiveWords = new ArrayList<>();
        Map<Object, Object> currMap = sensitiveWordMap;
        for (int i = 0; i < text.length(); i++)
        {
            Character word = text.charAt(i);
            Object wordMap = currMap.get(word);
            if (wordMap == null)
            {
                continue;
            }
            int j = i + 1;
            Map<Object, Object> childMap = (Map<Object, Object>)wordMap;
            while (j < text.length())
            {
                if (Boolean.valueOf(childMap.get("isEnd").toString()))
                {
                    sensitiveWords.add(text.substring(i, j));
                }
                wordMap = childMap.get(text.charAt(j));
                if (wordMap != null)
                {
                    childMap = (Map<Object, Object>)wordMap;
                }
                else
                {
                    break;
                }
                j++;
            }
        }
        return sensitiveWords;
    }
    
    /**
    * 检查一个字符串从begin位置起开始是否有keyword符合， 如果有符合的keyword值，返回值为匹配keyword的长度，否则返回零
    * flag 1:最小长度匹配 2：最大长度匹配
    */
    @SuppressWarnings("unchecked")
    public static int checkKeyWords(String txt, int begin, int flag)
    {
        Map<Object, Object> currMap = sensitiveWordMap;
        int maxMatchRes = 0;
        int res = 0;
        for (int i = begin; i < txt.length(); i++)
        {
            char word = txt.charAt(i);
            Object wordMap = currMap.get(word);
            if (wordMap != null)
            {
                res++;
                currMap = (Map<Object, Object>)wordMap;
                if (Boolean.valueOf(currMap.get("isEnd").toString()))
                {
                    if (flag == 1)
                    {
                        wordMap = null;
                        currMap = null;
                        txt = null;
                        return res;
                    }
                    else
                    {
                        maxMatchRes = res;
                    }
                }
            }
            else
            {
                txt = null;
                currMap = null;
                return maxMatchRes;
            }
        }
        return maxMatchRes;
    }
    
    /**
     * 返回txt中关键词列表
     * @param txt
     * @return
     */
    public static Set<String> getTxtKeyWords(String txt)
    {
        Set<String> set = new HashSet<>();
        for (int i = 0; i < txt.length();)
        {
            int len = checkKeyWords(txt, i, 1);
            if (len > 0)
            {
                set.add(txt.substring(i, i + len));
                i += len;
            }
            else
            {
                i++;
            }
        }
        return set;
    }
    
    /**
     * 返回过滤后的关键词列表，并关键词替换为*
     * @param txt
     * @return
     */
    public static String getFilerWords(String txt)
    {
        String filterWords = txt;
        for (int i = 0; i < txt.length();)
        {
            int len = checkKeyWords(txt, i, 1);
            if (len > 0)
            {
                filterWords = filterWords.replaceAll(txt.substring(i, i + len), "**");
                i += len;
            }
            else
            {
                i++;
            }
        }
        return filterWords;
    }
    
    public static void main(String[] args)
    {
        Set<String> words = new HashSet<String>();
        words.add("中国人");
        words.add("傻逼");
        words.add("黑鬼");
        createSensitiveWordMap(words);
        System.out.println(sensitiveWordMap.toString());
        System.out.println(checkSensitiveWord("中国人对美国人说黑鬼是个傻逼站起来了"));
        System.out.println(getFilerWords("中国人对美国人说黑鬼是个傻逼站起来了"));
    }
}
